package com.ls.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class SelectorServer {
    private static Selector selector;

    public static void main(String[] args) throws IOException {

        selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(8088));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while(true){
            if(selector.select(50) > 0){
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> itr = selectionKeys.iterator();

                while(itr.hasNext()){
                    SelectionKey selectionKey = itr.next();
                    itr.remove();

                    if(selectionKey.isAcceptable()){
                        handleAccept(selectionKey);
                    }else if(selectionKey.isReadable()){
                        handleReadable(selectionKey);

//                        new Thread(() ->{
//                            try {
//                                while(true){
//                                    System.out.println("isValid:" + selectionKey.isValid());
//                                    System.out.println("isConnectable:" + selectionKey.isConnectable());
//                                    TimeUnit.SECONDS.sleep(1);
//                                }
//                            } catch (InterruptedException e) {
//                                e.printStackTrace();
//                            }
//                        }).start();

                    }else if(selectionKey.isWritable()){
                        handleWritable(selectionKey);
                    }else if(selectionKey.isConnectable()){
                        System.out.println("isConnectable");
                    }else if(selectionKey.isValid()){
                        System.out.println("isValid");
                    }

                }
            }
        }


    }

    private static void handleAccept(SelectionKey selectionKey) throws IOException {
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
        SocketChannel socketChannel = serverSocketChannel.accept();

        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocateDirect(1024));
    }

    private static void handleReadable(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
        try{

            byteBuffer.clear();
            int num = socketChannel.read(byteBuffer);
            if(num > 0){
                byteBuffer.flip();
                byte[] bytes = new byte[byteBuffer.limit()];
                byteBuffer.get(bytes);
                System.out.println("read: " + new String(bytes));

                byteBuffer.flip();
                socketChannel.register(selector, SelectionKey.OP_WRITE, byteBuffer);
            }else if(num == -1){
                System.out.println("连接关闭");
                selectionKey.cancel();
            }

//        ByteBuffer byteBuffer1 = ByteBuffer.wrap("\nanther msg".getBytes());
//        socketChannel.register(selector, SelectionKey.OP_WRITE, byteBuffer1);

        }catch (Exception e){
            selectionKey.cancel();
            e.printStackTrace();
        }
    }

    private static void handleWritable(SelectionKey selectionKey) throws IOException {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("write: ......");
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();

        ByteBuffer data = ByteBuffer.allocateDirect(1024);
        data.put("i have receive: ".getBytes());

        data.put(byteBuffer);

        data.flip();
        socketChannel.write(data);

        selectionKey.interestOps(SelectionKey.OP_READ);
    }



}
